#include "rtc.h" 
  
 #include <pc.h> 
 #include <stdio.h> 
 #include <stdlib.h> 
  
 /** converts BCD (Binary Coded Decimal) to decimal 
  */ 
 Byte bcd2dec(Byte i) 
 { 
         Byte dec = 0; 
         dec += ((0x0F0 & i) >> 4) * 10; 
         dec += 0x0F & i; 
         return dec; 
 } 
  
 /** converts decimal to BCD (Binary Coded Decimal) 
  */ 
 Byte dec2bcd(Byte i) 
 { 
         Byte bcd = 0; 
         bcd |= i % 10; 
         bcd |= (i / 10) << 4; 
         return bcd; 
 } 
  
 /** Wait until data in rtc is valid. 
  * Data is valid until +/- 240 usec after this function returns, 
  * thus a read/write can be done to the RTC within this time period 
  */ 
 void rtc_valid() 
 { 
         int ints_en = disable(); 
         outportb(RTC_ADDR_REG, RTC_STAT_A); 
         while(inportb(RTC_STAT_A) && RTC_UIP == 0); 
         if (ints_en) 
                 enable(); 
 } 
  
 /** Returns rtc data from I/O address add. Doesn't check valid bit 
  */ 
 Byte read_rtc(Byte add) 
 { 
         Byte ret; 
         disable(); 
         outportb(RTC_ADDR_REG, add); 
         ret = inportb(RTC_DATA_REG); 
         enable(); 
         return ret; 
 } 
  
 /** Returns rtc data from I/O address add. Check valid bit 
  */ 
 Byte read_rtcv(Byte add) 
 { 
         rtc_valid(); 
         return read_rtc(add); 
 } 
  
 /** Write value to I/O address add. Doesn't check valid bit 
  */ 
 void write_rtc(Byte add, Byte value) 
 { 
         disable(); 
         outportb(RTC_ADDR_REG, add); 
         outportb(RTC_DATA_REG, value); 
         enable(); 
 } 
  
 /** Write value to I/O address add. Check valid bit 
  */ 
 void write_rtcv(Byte add, Byte value) 
 { 
         rtc_valid(); 
         write_rtc(add, value); 
 } 
  
 /** Read RTC stored time 
  * 
  * Uses read_rtcv() and bcd2dec() 
  */ 
 void rtc_read_time(RTC_TIME *time) 
 { 
         time->sec = bcd2dec(read_rtcv(SEC)); 
         time->min = bcd2dec(read_rtcv(MIN)); 
         time->hour = bcd2dec(read_rtcv(HOUR)); 
 } 
  
 /** Read RTC stored date 
  * 
  * Uses read_rtcv() and bcd2dec() 
  */ 
 void rtc_read_date(RTC_DATE *date) 
 { 
         date->day = bcd2dec(read_rtcv(MONTH_DAY)); 
         date->month = bcd2dec(read_rtcv(MONTH)); 
         date->year = bcd2dec(read_rtcv(YEAR)); 
 } 
  
 /** Read RTC stored alarm 
  * 
  * Uses read_rtcv() and bcd2dec() 
  */ 
 void rtc_read_alarm(RTC_TIME *time) 
 { 
         time->sec = bcd2dec(read_rtcv(SEC_ALARM)); 
         time->min = bcd2dec(read_rtcv(MIN_ALARM)); 
         time->hour = bcd2dec(read_rtcv(HOUR_ALARM)); 
 } 
  
 /** Write alarm to RTC 
  * 
  * Uses write_rtcv() and dec2bcd() 
  */ 
 void rtc_write_alarm(RTC_TIME *time) 
 { 
         write_rtcv(SEC_ALARM, dec2bcd(time->sec)); 
         write_rtcv(MIN_ALARM, dec2bcd(time->min)); 
         write_rtcv(HOUR_ALARM, dec2bcd(time->hour)); 
 } 
